// ----------------------------------------
// Filename: SPI.c
// Description: Routines to implement an MSSP SPI
// Author: Anton Jatmiko
// Date: 22 April 2014

#include "SPI.h"

// ----------------------------------------
// SPI_Init
//
// Initialise SPI and its peripheral
// Input:
//   none
// Output:
//   none
// Conditions:
//   none
void SPI_Init(void)
{
    TRISDbits.RD0 = 0;              // Reset SCK2 to output
    TRISDbits.RD2 = 0;              // Reset SDO2 to output
    TRISDbits.RD3 = 0;              // Reset SS2 pin to output (general digital out)
    SSP2STATbits.SMP = 1;           // Input sampled at the end of ouput time,
    SSP2STATbits.CKE = 1;           // Transmit occur on transition from HIGH to LOW, CPHA = 0
    SSP2CON1bits.CKP = 0;           // Idle clk state at low, CPOL = 0
    SSP2CON1bits.SSPEN = 1;         // Enable SPI ports
    //SSP2CON1bits.SSPM = 1;          // SPI master mode, clk = Fosc/16
    SSP2CON1bits.SSPM = 2;          // SPI master mode, clk = Fosc/64

    PIR3bits.SSP2IF = 0;            // Reset MSSP 2 Interrupt Flag
    IPR3bits.SSP2IP = 1;            // Set MSSP interrupt priority to high
    PIE3bits.SSP2IE = 0;            // Disable MSSP 2 Interrupt
}

// ----------------------------------------
// SPI_Put
//
// Send data to the slave
// Input:
//   data is the data to be sent
// Output:
//   TRUE if data is sent
// Conditions:
//   assume SPI has been initialised
BOOL SPI_Put(UINT8 data)
{
    UINT8 dummyVar;

    dummyVar = SSP2BUF;             // Empty SSP2BUF
    SSP2CON1bits.WCOL = 0;          // Clear any collision
    SSP2BUF = data;                 // Write data to buffer

    return (!SSP2CON1bits.WCOL);
}

// ----------------------------------------
// SPI_Get
//
// Read data from the slave
// Input:
//   dataPtr is a pointer to the data read
// Output:
//   TRUE if data is read
// Conditions:
//   assume SPI has been initialised
BOOL SPI_Get(UINT8 * const dataPtr)
{
    if (SSP2STATbits.BF)
    {
        *dataPtr = SSP2BUF;
        return bTRUE;
    }
    return bFALSE;
}

// ----------------------------------------
// SPI_SetInterrupt
//
// Arm or disarm SPI interrupt
// Input:
//   enable is a boolean indicates whether to arm or disarm SPI interrupt
// Output:
//   none
// Conditions:
//   none
void SPI_SetInterrupt(BOOL enable)
{
    PIE3bits.SSP2IE = enable;            // Arm or disarm MSSP 2 Interrupt
}